package com.atguigu.exam.service.impl;

import com.atguigu.exam.entity.PaperQuestion;
import com.atguigu.exam.entity.Question;
import com.atguigu.exam.entity.QuestionAnswer;
import com.atguigu.exam.entity.QuestionChoice;
import com.atguigu.exam.exception.ExamException;
import com.atguigu.exam.mapper.PaperQuestionMapper;
import com.atguigu.exam.mapper.QuestionAnswerMapper;
import com.atguigu.exam.mapper.QuestionChoiceMapper;
import com.atguigu.exam.mapper.QuestionMapper;
import com.atguigu.exam.service.QuestionService;
import com.atguigu.exam.vo.QuestionQueryDto;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.internal.constraintvalidators.bv.time.futureorpresent.FutureOrPresentValidatorForCalendar;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * 题目Service实现类
 * 实现题目相关的业务逻辑
 */
@Slf4j
@Service
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question> implements QuestionService {

    @Autowired
    private QuestionAnswerMapper questionAnswerMapper;
    @Autowired
    private QuestionChoiceMapper questionChoiceMapper;
    @Autowired
    private PaperQuestionMapper paperQuestionMapper;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;


    /*
    分页及带条件查询
    * */
    @Override
    public Page<Question> getPageByCondition(Page<Question> page1, QuestionQueryDto dto) {
        //调用QuestionMapper中分页带查询的方法
        Page<Question> questionPage = baseMapper.getPageByCondition(page1, dto);
        return questionPage;
    }

    /*
    根据id查询题目详情
    * */
    @Override
    public Question getQuestionById(Long id) {
        Question questionDetailById = baseMapper.getQuestionDetailById(id);
        //创建一个多线程,获取查询的次数
        new Thread(()->{
            redisTemplate.opsForZSet().incrementScore("question:popular",id,1.0);
        }).start();
        return questionDetailById;
    }

    /*
    创建题目
    * */
    @Override
    public void createQuestion(Question question) {
        /*//判断在当前类型中是否存在该题目
        boolean exists = baseMapper.exists(new LambdaQueryWrapper<Question>().eq(Question::getType, question.getType()).eq(Question::getTitle, question.getTitle()));
        if (exists) {
            throw new ExamException(444, "该类型在<" + question.getType() + "已经存在,请重新输入");
        }
        //保存题目
        baseMapper.insert(question);
        //获取题目答案
        QuestionAnswer answer = question.getAnswer();
        //获取题目id
        Long questionId = question.getId();
        //给答案添加id
        answer.setQuestionId(questionId);

        //判断是否为选择题
        if ("CHOICE".equals(question.getType())) {
            //获取题目选项
            List<QuestionChoice> choices = question.getChoices();
            //创建一个StringBuilder对象 用于拼接选项
            StringBuilder stringBuilder = new StringBuilder();
            //遍历选项
            for (int i = 0; i < choices.size(); i++) {
                //获取每一个选项
                QuestionChoice questionChoice = choices.get(i);
                //设置选项id
                questionChoice.setQuestionId(questionId);
                //对选项进行排序
                questionChoice.setSort(i);
                //如果是选择题目保存选项
                questionChoiceMapper.insert(questionChoice);
                if (questionChoice.getIsCorrect()) {
                    if (stringBuilder.length() > 0) {
                questionChoiceMapper.insert(questionChoice);
                        stringBuilder.append(",");
                    }
                    stringBuilder.append((char) ('A' + i));
                }
            }
            //将正确答案放到answer中
            answer.setAnswer(stringBuilder.toString());
        }
        questionAnswerMapper.insert(answer);*/
        //判断当前类型下是否有该题目
        boolean exists = baseMapper.exists(new LambdaQueryWrapper<Question>().eq(Question::getType, question.getType()).eq(Question::getTitle, question.getTitle()));
        if (exists){
            throw new ExamException(444, "该类型在<" + question.getType() + "已经存在,请重新输入");
        }
        //保存题目
        baseMapper.insert(question);
        //获取题目答案
        QuestionAnswer answer = question.getAnswer();
        //获取题目id
        Long questionId = question.getId();
        //给答案设置id
        question.setId(questionId);
        //判断是否为选择题
        if ("CHOICE".equals(question.getType())){
            //获取选项
            List<QuestionChoice> choices = question.getChoices();
            //遍历选项
            for (int i = 0; i < choices.size(); i++) {
                //获取每一个选项
                QuestionChoice questionChoice = choices.get(i);
                //给选项设置id
                questionChoice.setQuestionId(questionId);
                //选项排序
                questionChoice.setSort(i);
                //如果为选择保存
                questionChoiceMapper.insert(questionChoice);
                //创建StringBuilder对象用于拼接
                StringBuilder stringBuilder = new StringBuilder();
                //判断是否为正确选项
                if (questionChoice.getIsCorrect()){
                    if (stringBuilder.length()>0){
                        stringBuilder.append(",");
                    }
                    stringBuilder.append((char)('A'+i));
                }
                //将正确选项保存到答案中
                answer.setAnswer(stringBuilder.toString());
            }
            questionAnswerMapper.insert(answer);
        }
    }
    /* //判断当前类型下是否有该题目
        boolean exists = baseMapper.exists(new LambdaQueryWrapper<Question>().eq(Question::getTitle, question.getTitle()).eq(Question::getType, question.getType()));
        if(exists){
            throw new ExamException(444,"当前类型<"+question.getType()+">已经存在,请重新输入");
        }
        //保存题目
        baseMapper.insert(question);
        //获取题目答案
        QuestionAnswer answer = question.getAnswer();
        //获取题目自增长的id
        Long questionId = question.getId();
        //给答案添加id
        answer.setQuestionId(questionId);

        //判断是否为选择题
        if ("CHOICE".equals(question.getType())){
            //获取题目选项
            List<QuestionChoice> choices = question.getChoices();
            //创建StringBulider对象 用于拼接内容
            StringBuilder stringBuilder = new StringBuilder();
            //遍历选项
            for (int i = 0; i < choices.size(); i++) {
                //获取每一个选项
                QuestionChoice questionChoice = choices.get(i);
                //给每一个选项设置id
                questionChoice.setQuestionId(questionId);
                //设置选项的排序
                questionChoice.setSort(i);
                //如果是选择题保存选项
                questionChoiceMapper.insert(questionChoice);
                if (questionChoice.getIsCorrect()){
                    if (stringBuilder.length()>0){
                        stringBuilder.append(",");
                    }
                    stringBuilder.append((char)('A'+i));
                }
                answer.setAnswer(stringBuilder.toString());
            }
            questionAnswerMapper.insert(answer);
        }*/

    /*
    更新题目
    * */
    @Override
    public void updateQuestion(Question question) {
     /*//创建一个LambdaQueryWrapper对象
        LambdaQueryWrapper<Question> questionLambdaQueryWrapper = new LambdaQueryWrapper<>();
     //封装查询条件
     questionLambdaQueryWrapper.eq(Question::getTitle,question.getTitle())
             .eq(Question::getType,question.getType())
             .ne(Question::getId,question.getId());
     //判断更新之后的题目在当前类型中是否已经存在
        boolean exists = baseMapper.exists(questionLambdaQueryWrapper);
        if (exists){
            throw new ExamException(555,"当前类型下<"+question.getType()+">已经存在,请重新输入");
        }
        //保存题目
        baseMapper.updateById(question);
        //获取题目答案
        QuestionAnswer answer = question.getAnswer();
        //判断是否为选择题
        if ("CHOICE".equals(question.getType())){
            //删除原有的选项
            questionChoiceMapper.delete(new LambdaQueryWrapper<QuestionChoice>().eq(QuestionChoice::getQuestionId,question.getId()));
            //获取题目选项
            List<QuestionChoice> choices = question.getChoices();
            //创建StringBulider对象
            StringBuilder stringBuilder = new StringBuilder();
            //遍历选项
            for (int i = 0; i < choices.size(); i++) {
                //获取每一个选项
                QuestionChoice questionChoice = choices.get(i);
                //选项表中已经有id只是更新 所有设置更新的题目选项id为null
                questionChoice.setId(null);
                //设置更新和创建时间也为null
                questionChoice.setCreateTime(null);
                questionChoice.setUpdateTime(null);
                //设置选项顺序
                questionChoice.setSort(i);
                //保存选项
                questionChoiceMapper.insert(questionChoice);
                if (questionChoice.getIsCorrect()){
                    if (stringBuilder.length()>0){
                        stringBuilder.append(",");
                    }
                    stringBuilder.append((char)('A'+i));
                }
            }
            //将正确的答案保存到答案表中
            answer.setAnswer(stringBuilder.toString());
        }
        //更新正确的题目答案
        questionAnswerMapper.updateById(answer);*/
        LambdaQueryWrapper<Question> questionLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //封装查询条件
        questionLambdaQueryWrapper.eq(Question::getTitle,question.getTitle())
                .eq(Question::getType,question.getType())
                .ne(Question::getId,question.getId());
        //判断更新后的题目在当前类型下已经存在
        boolean exists = baseMapper.exists(questionLambdaQueryWrapper);
        if (exists){
            throw  new ExamException(555,"当前类型下<"+question.getType()+">已经存在,请重新输入");
        }
        //保存题目
        baseMapper.insert(question);
        //获取题目答案
        QuestionAnswer answer = question.getAnswer();
        //判断是否为选择
        if ("CHOICE".equals(question.getType())){
            //删除原来的选项
            questionChoiceMapper.delete(new LambdaQueryWrapper<QuestionChoice>().eq(QuestionChoice::getId,question.getId()));
            //获取选项
            List<QuestionChoice> choices = question.getChoices();
            StringBuilder stringBuilder = new StringBuilder();
            //遍历选项
            for (int i = 0; i < choices.size(); i++) {
                //获取每一个选项
                QuestionChoice questionChoice = choices.get(i);
                //设置选项id为null
                questionChoice.setId(null);
                //设置创建和更新时间为null
                questionChoice.setCreateTime(null);
                questionChoice.setUpdateTime(null);
                //保存选项
                questionChoiceMapper.insert(questionChoice);
                if (questionChoice.getIsCorrect()){
                    if (stringBuilder.length()>0){
                        stringBuilder.append(",");
                    }
                    stringBuilder.append((char)('A'+i));
                }
                answer.setAnswer(stringBuilder.toString());
            }
            questionAnswerMapper.insert(answer);
        }
    }
    /*
    删除题目
    * */
    @Transactional
    @Override
    public Boolean deleteQuestion(Long id) {
       /* //判断当前题目下是否有试卷
        Long l = paperQuestionMapper.selectCount(new LambdaQueryWrapper<PaperQuestion>().eq(PaperQuestion::getQuestionId, id));
        //判断是否存在
        if (l>0){
            throw new ExamException(666,"当前题目下已经存在试卷,不能删除");
        }
        //删除题目
        baseMapper.deleteById(id);
        //根据id删除题目答案
        questionAnswerMapper.delete(new LambdaQueryWrapper<QuestionAnswer>().eq(QuestionAnswer::getQuestionId, id));
        //根据id删除题目题目
         questionChoiceMapper.delete(new LambdaQueryWrapper<QuestionChoice>().eq(QuestionChoice::getQuestionId, id));
        return true;*/
        //判断当前题目下是否有试卷
        Long l = paperQuestionMapper.selectCount(new LambdaQueryWrapper<PaperQuestion>().eq(PaperQuestion::getQuestionId, id));
        if (l>0){
            throw new ExamException(666,"当前题目下已经存在试卷,不能删除");
        }
        //删除题目选项
        questionChoiceMapper.delete(new LambdaQueryWrapper<QuestionChoice>().eq(QuestionChoice::getQuestionId,id));
        //删除题目答案
        questionAnswerMapper.delete(new LambdaQueryWrapper<QuestionAnswer>().eq(QuestionAnswer::getId,id));
        return true;
    }

   @Override
    public List<Question> getPopularQusetions(Integer size) {
     /*   //获取热门题目id
       Set<Object> redisqustionsId = redisTemplate.opsForZSet().reverseRange("question:popular", 0, size - 1);
       //根据id获取热门题目
       List<Question> redisquestions = baseMapper.selectList(new LambdaQueryWrapper<Question>().in(Question::getId, redisqustionsId));
       //将题目顺序翻转
       Collections.reverse(redisquestions);
       //获取热门题目数量
       int redisSize = redisquestions.size();
       int diff =size-redisSize;
       //判断人们题目数量是否达到size
       if (diff>0){
           //说明热门题目达不到 需要sql补入
           LambdaQueryWrapper<Question> questionLambdaQueryWrapper = new LambdaQueryWrapper<>();
           //封装查询条件 降序排列
           questionLambdaQueryWrapper.orderByDesc(Question::getCreateTime);
           //查询的题目是redis中不包含的题目
           questionLambdaQueryWrapper.notIn(Question::getId,redisqustionsId);
           //在整个sql语句后加limit
           questionLambdaQueryWrapper.last("limit "+diff);
           //执行带条件的查询
           List<Question> questions = baseMapper.selectList(questionLambdaQueryWrapper);
           //将查询出来的题目添加到redisQuestion中
           redisquestions.addAll(questions);
       }
       return redisquestions;*/
      /* //获取热门题目的id
       Set<Object> questionId = redisTemplate.opsForZSet().reverseRange("question.popular", 0, size - 1);
       //根据热门id获取题目
       List<Question> questions = baseMapper.selectList(new LambdaQueryWrapper<Question>().eq(Question::getId, questionId));
       //将题目顺序调转
       Collections.reverse(questions);
       //获取题目数量
       int size1 = questions.size();
       int diff=size-size1;
       //判断题目数量是否达到size数量
       if (diff>0){
           //数量没有达到 需要sql补入
           //创建LambdaQueryWrapper对象
           LambdaQueryWrapper<Question> questionLambdaQueryWrapper = new LambdaQueryWrapper<>();
           //封装查询条件
           questionLambdaQueryWrapper.orderByDesc(Question::getCreateTime);
           //不能包含redis的热门题目
           questionLambdaQueryWrapper.notIn(Question::getId,questionId);
           //在sql语句后加limit
           questionLambdaQueryWrapper.last("limit "+diff);
           //执行带条件的查询
           List<Question> questions1 = baseMapper.selectList(questionLambdaQueryWrapper);
           //将查询出来的题目添加到redis热门题目中
           questions.addAll(questions1);
       }
       return questions;*/
       //获取radis热门题目
       Set<Object> redisquestionId = redisTemplate.opsForZSet().reverseRange("question.popular", 0, size - 1);
       //根据id获取题目
       List<Question> questions = baseMapper.selectList(new LambdaQueryWrapper<Question>().eq(Question::getId, redisquestionId));
       //获取题目数量
       int size1 = questions.size();
       int diff=size-size1;
       if (diff>0){
           //需要sql补入
           LambdaQueryWrapper<Question> questionLambdaQueryWrapper = new LambdaQueryWrapper<>();
           //封装查询条件 降序
           questionLambdaQueryWrapper.orderByDesc(Question::getCreateTime);
           //要确保题目不是redis中的题目
           questionLambdaQueryWrapper.notIn(Question::getId,redisquestionId);
           //在sql语句后加limit
           questionLambdaQueryWrapper.last("limit "+diff);
           //调用带条件的查询
           List<Question> questions1 = baseMapper.selectList(questionLambdaQueryWrapper);
           //将题目加入redis热门题目中
           questions.addAll(questions1);
       }
       return questions;
   }


}

